Repository navigation
Core seams for integrations: target lifecycle hooks, tool events, injected clients - #121
Merged
Merged
Conversation
Records, for 28 audit configurations, everything the engine sends to the target, auditor and judge clients, the stored results and the on_turn events, and compares them with JSON files in tests/snapshots/core/. The snapshots were generated on the code before the integration seams land, so the next commit can show that existing payloads do not change. Run ids, image bytes and the checkout path are normalised. Regenerate with SIMPLEAUDIT_UPDATE_SNAPSHOTS=1 when a change is intended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seams for auditing agents and running inside other frameworks. Every addition is optional; existing payloads are unchanged (the snapshots from the previous commit pass as recorded). - Targets may define async start_scenario(context) / end_scenario(context). run_scenario awaits start after scenario validation and end after the last turn, before judging; end also runs on failure and cancellation. Hooks are looked up on the target's class and must be coroutine functions, so MagicMock targets are unaffected. run_scenario now binds self.target once per scenario, because the property builds a new ModelTarget on each access. - TargetResponse.tool_events: an agent's tool calls and results for the turn. Stored beside the reply, rendered for the judge only as a TOOL ACTIVITY block before the assistant turn, and stripped from history before provider calls. - TargetResponse.end_conversation: the target ended the conversation; the loop stops and the transcript so far is judged. - ModelAuditor(judge_client=..., auditor_client=...): ready-made clients replace AnyLLM creation for that role. An injected auditor client wins over every fallback; without one, the existing branches apply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
- Tool events are stored as a JSON-safe copy (non-JSON values become strings, so results can always be saved) and must be a list of dicts; anything else fails that turn with a clear error. - The judge sees at most 50 tool events per turn. Values are rendered as JSON, strings included, so tool output stays on one line and cannot pose as a transcript turn; the block is labelled as tool data. An id of 0 and string error messages are kept, and a turn with no tool call or result adds no block. - Tool events are left out of the history passed to targets, and provider messages are reduced to role and content in one place. - end_scenario now runs after the evidence resolver, so a resolver can still read the target's session, and a failing end_scenario raises a RuntimeWarning instead of logging only with verbose=True. - Hooks are looked up on the target itself (proxies work); a hook defined without async is not called and warns. - With an injected judge_client, an auditor of its own needs auditor_client or both auditor_model and auditor_provider, instead of falling back to the judge's labels. - reframing_check rejects transforms that change tool_events. - README: the hook rules as implemented, and judge_client/auditor_client in the parameter table.
kelkalot
added a commit
that referenced
this pull request
Oct 24, 2026
kelkalot
added a commit
that referenced
this pull request
Oct 24, 2026
A turn with more than 50 tool events now shows the first 25 and the last 25 with a count of the ones in between. An agent's last actions are often the decisive ones, and cutting the tail hid them from the judge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds optional extension points to the audit engine:
#122 (Inspect AI) and #123 (OpenEnv) build on them.
Changes
async start_scenario(context)andasync end_scenario(context).run_scenarioawaitsstart_scenarioafter scenario validation.start_scenariohas succeeded,end_scenarioruns after the last turn and the evidence resolver, before judging. It also runs when a turn fails or the run is cancelled. A failingend_scenarioraises aRuntimeWarningand doesn't change the result.asyncis skipped with a warning.context.scenario_run_idmatches the per-turn contexts, andcontext.extra["scenario_name"]names the scenario.run_scenarionow readsself.targetonce per scenario. Withoutset_target, the property builds a newModelTargeton every access.TargetResponse.tool_events. The agent's tool calls and results for the turn, as a list of dicts.TOOL ACTIVITYblock before the assistant turn.TargetResponse.end_conversation. Stops the turn loop after this reply; the transcript so far is judged.judge_client=/auditor_client=onModelAuditor, and so onAuditor. A ready-made client, with the same contractrejudgetakes, replaces AnyLLM client creation for that role, and the provider and model arguments become labels.auditor_client, or bothauditor_modelandauditor_provider.reframing_checkrejects a transform that changestool_events.Compatibility
Everything above is optional, and existing payloads are unchanged.
tests/test_core_snapshots.pyrecords the following for 28 configurations, and compares them with JSON files intests/snapshots/core/:on_turnevents.The snapshots were recorded on the code before this change and pass as recorded. Regenerate them with
SIMPLEAUDIT_UPDATE_SNAPSHOTS=1only when a payload change is intended.Limitations
SingleTurnAuditordoesn't call the hooks and doesn't store tool events.Tests
tests/test_integration_seams.pyhas 30 tests. They cover:end_scenario;Live checks, with
claude-haiku-5-5as target, auditor and judge:nav_aapaudit ran through the unchanged model path.datetimeinside the tool events survived saving and loading.